<?php


namespace App\Services\Tools;

//第三方 未知 zxx  2024 06 14
use App\Repositories\LogRepository;
use App\Exceptions\BasicException;
use Carbon\Carbon;

class SmsSanFangService
{

    private static $_error_code = '';
    private static $_error_msg = '';
    //发送
    public static function send($mobile, $type, $param = [], $limit = 1,$template_id="")
    {
        $key = 'sms:' . $mobile . ':' . $type;
        if ($limit > 0 && app('redis')->get($key)) {
            throw new BasicException(0, $limit . '分钟可获取一次');
        }
        //短信发送
        $url = 'http://110.40.226.85:9511';
        $spId = '621330';
        $password = '4ebf95b8';
        $action = '/api/send-sms-single';
        $mb_content = '【欣然】验证码：%，该验证码5分钟内有效，请勿泄漏于他人！';
        $search ='%';
        //$sms_code = isset($param['code'])?$param['code']:self::getRandCode();
        $sms_code = isset($param['code'])?$param['code']:self::getRandCode();
        $content = str_replace($search, $sms_code, $mb_content);
        $postData = array(
            'sp_id' => $spId,
            'mobile' => $mobile,
            'content' => $content,
        );

        $usePassword = true;
        //如果是使用得密码发送
        if ($usePassword) {
            $postData['password'] = md5($password);
        } else {
            $postData['signature'] = self::generateSignature($postData, 'POST', $password);
        }


        if (env('SMS_REAL_SEND')) {
            if (!self::doCurl($postData, $url, $action)) {
                throw new BasicException(0, '发送失败');
            }
        }

        app('model_sms_history')->create([
            'mobile'   => $mobile,
            'code'     => $sms_code,
            'add_time' => Carbon::now()->timestamp,
            'type'     => $type
        ]);

        app('redis')->setex($key, $limit*60, $sms_code);
        return true;

    }

    protected static function generateSignature($data, $method, $password)
    {
        ksort($data);
        $uri = $method . '&' . urlencode('/') . '&' . preg_replace(['/\+/', '/\*/', '/%7E/'], ['%20', '%2A', '~'], http_build_query($data));
        return base64_encode(hash_hmac("sha1", $uri, $password));
    }

    private static function getRandCode(){
        return mt_rand(1000, 9999);
    }
    protected static function doCurl($data, $url, $action)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url . $action);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        $output = curl_exec($ch);
        curl_close($ch);
        $output = json_decode($output,true);
        $verify_code = $output['code'] ?? 1;
        if($verify_code != 0){
            // 记录失败
            $logRtx = new LogRepository("sms-send");
            $logRtx->log("output",$output);
            $logRtx->File();
        }

        return $verify_code == 0 ? true : false;
    }

    public static function verify($mobile, $code, $type) {
        $where = [
            'mobile' => $mobile,
            'type' => $type,
            'status' => 0,
        ];
        $data = app('model_sms_history')->where($where)->orderBy('id', 'desc')->first();
        $result = false;
        $key = 'u:login_error_times:'.$mobile.':'.$type;

        if (isset($data) && $data->status == 0 && $data->code == $code) {
            if ($data->add_time < (Carbon::now()->timestamp - 1800)) {
                $status = 2;
                $result = false;
                self::$_error_msg = '验证码已过期';
            } else {
                $status = 1;
                $result = true;
            }
            app('model_sms_history')->where(['id' => $data->id, 'status' => 0])->update([
                'status'      => $status,
                'update_time' => Carbon::now()->timestamp
            ]);

        }
        //记录错误次数
        if(!$result){
            self::$_error_msg = '验证码错误';
            $times = app('redis')->incr($key);
            if ($times >= 5) {
                app('model_sms_history')->where($where)->update([
                    'status'      => 2,
                    'update_time' => Carbon::now()->timestamp
                ]);
                self::$_error_msg = '验证码输入错误次数过多，已失效，请重新获取';
                app('redis')->del($key);
                return false;
            } elseif ($times == 1) {
                app('redis')->expire($key,strtotime(date('Ymd')) + 86400 - time());
            }
        }
        return $result;
    }
    public static function getErrorMsg(){
        return [
            'error_code' => self::$_error_code,
            'error_msg' => self::$_error_msg,
        ];
    }
}
